package org.lep.leetcode.binarytreemaximumpathsum;

/**
 *
 * Source : https://oj.leetcode.com/problems/binary-tree-maximum-path-sum/
 *
 * Created by lverpeng on 2017/8/21.
 *
 * Given a binary tree, find the maximum path sum.
 *
 * The path may start and end at any node in the tree.
 *
 * For example:
 * Given the below binary tree,
 *
 *        1
 *       / \
 *      2   3
 *
 * Return 6.
 */
public class BinaryTreeMaximumPathSum {


    /**
     * 求出遍历树节点的时候最大和，
     * 可以从任何地方开始遍历，可以在任何地方结束
     *
     * 分析得出有两种遍历方式：
     * 1. 从根节点到叶子节点之间的一段，root-leaf path中的一段
     * 2. 两个节点之间经过最小公共祖先节点的path
     *
     * 分别对于两种情况求出最大值，然后比较求出较大的一个
     *
     * 定义：
     * sum1为第一种情况下，一个节点可能出现的最大值
     * sum1(root) = max(max(sum1(root.left), 0), max(sum1(root.right), 0)) + root.value
     *
     * sum2为第二种情况下，一个节点可能出现的最大值
     * sum2(root) = max(sum1(root.left), 0) + max(sum1(root.right), 0) + root.value
     *
     *
     * @param root
     * @return
     */
    public int maxPathSum (TreeNode root) {
        MaxSumHolder holder = new MaxSumHolder();
        holder.value = Integer.MIN_VALUE;
        return recursion(root, holder);
    }


    public int recursion (TreeNode root, MaxSumHolder holder) {
        if (root == null) {
            return 0;
        }
        int sum1Left = 0;
        int sum1Right = 0;
        if (root.leftChild != null) {
            sum1Left = Math.max(recursion(root.leftChild, holder), 0);
        }

        if (root.rightChild != null) {
            sum1Right = Math.max(recursion(root.rightChild, holder), 0);
        }
        int sum1 = Math.max(sum1Left, sum1Right) + root.value;
        int sum2 = sum1Left + sum1Right + root.value;
        holder.value = Math.max(holder.value, Math.max(sum1, sum2));

        return holder.value;
    }

    private class MaxSumHolder {
        int value;
    }



    public TreeNode createTree (char[] treeArr) {
        TreeNode[] tree = new TreeNode[treeArr.length];
        for (int i = 0; i < treeArr.length; i++) {
            if (treeArr[i] == '#') {
                tree[i] = null;
                continue;
            }
            tree[i] = new TreeNode(treeArr[i]-'0');
        }
        int pos = 0;
        for (int i = 0; i < treeArr.length && pos < treeArr.length-1; i++) {
            if (tree[i] != null) {
                tree[i].leftChild = tree[++pos];
                if (pos < treeArr.length-1) {
                    tree[i].rightChild = tree[++pos];
                }
            }
        }
        return tree[0];
    }

    private class TreeNode {
        TreeNode leftChild;
        TreeNode rightChild;
        int value;

        public TreeNode(int value) {
            this.value = value;
        }

        public TreeNode() {
        }
    }

    public static void main(String[] args) {
        BinaryTreeMaximumPathSum maximumPathSum = new BinaryTreeMaximumPathSum();
        char[] arr = new char[]{'1','2','3'};
        System.out.println( maximumPathSum.maxPathSum(maximumPathSum.createTree(arr)) + "----6");

    }

}
